package com.ebspp.server.storage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;

import com.ebspp.global.General;
import com.ebspp.thrift.DataMsg;

/**
 * A simple memory storage
 * It caches client data in memory
 * @author x23pan
 *
 */
public class SimpleMemStore implements IStore
{
	private Map<String, DataMsg> pIdx;
	private Map<String, Set<DataMsg>> sIdx;
	
	public SimpleMemStore()
	{
		pIdx = Collections.synchronizedMap(new HashMap<String, DataMsg>());
		sIdx = Collections.synchronizedMap(new HashMap<String, Set<DataMsg>>());
	}
	
	public List<DataMsg> read(DataMsg msg)
	{
		if(msg == null)
			return null;
		List<DataMsg> resList = new ArrayList<DataMsg>();
		
		if(msg.getKey() != null)
			resList.add(pIdx.get(msg.getKey()));
		else if(msg.getTs() != null)
		{
			Set<DataMsg> resSet = sIdx.get(msg.getTs());
			if(resSet != null)
				resList.addAll(resSet);
		}
		
		return resList;
	}

	public boolean write(DataMsg msg) 
	{
		// TODO Auto-generated method stub
		if(msg == null)
			return false;
		
		pIdx.put(msg.getKey(), msg);
		
		if(sIdx.get(msg.getTs()) == null)
		{
			Set<DataMsg> resSet = new HashSet<DataMsg>();
			sIdx.put(msg.getTs(), resSet);
		}
		sIdx.get(msg.getTs()).add(msg);
		
		return true;
	}
	
	public boolean delete(DataMsg msg)
	{
		if(msg == null)
			return false;
		
		if(msg.getKey() != null)
		{
			DataMsg res = pIdx.get(msg.getKey());
			if(res == null)
				return false;
			
			Set<DataMsg> resSet = sIdx.get(res.getTs());
			resSet.remove(res);
			return true;
		}
		else if(msg.getTs() != null)
		{
			Set<DataMsg> resSet = sIdx.get(msg.getTs());
			if(resSet == null)
				return false;
			
			for(DataMsg delMsg : resSet)
				pIdx.remove(delMsg.getKey());
			return true;
		}
		
		return false;
	}
	
	public List<DataMsg> bulkRead(List<DataMsg> data) 
	{
		if(data == null)
			return null;
		
		List<DataMsg> result = new ArrayList<DataMsg>();
		for(DataMsg msg : data)
			result.addAll(read(msg));
		
		return result;
	}


	@Override
	public List<DataMsg> bulkWrite(List<DataMsg> data) 
	{
		// TODO Auto-generated method stub
		List<DataMsg> failList = new ArrayList<DataMsg>();
		
		for(DataMsg msg : data)
			if(!write(msg))
				failList.add(msg);
		if(failList.size() == 0)
			return null;
		
		return failList;
	}

	@Override
	public List<DataMsg> garbageCollect(List<DataMsg> data) 
	{
		// TODO Auto-generated method stub
		List<DataMsg> failList = new ArrayList<DataMsg>();
		
		if(data == null)
			return data;
		
		for(DataMsg msg : data)
			if(!delete(msg))
				failList.add(msg);
		if(failList.size() == 0)
			return null;
		
		return failList;
	}
	
	@Override
	public boolean close() {
		// TODO Auto-generated method stub
		pIdx.clear();
		sIdx.clear();
		return true;
	}



}
